﻿// -------------------------------------------------------------------------------------------------------------------------------
// <copyright file="SlaeSolver{T}.cs" company="Exul">
//     Copyright (c) Exul. All rights reserved.
// </copyright>
// <author>
//     Exul
// </author>
// -------------------------------------------------------------------------------------------------------------------------------

namespace ExulLibrary.Mathematics.LinearAlgebra
{
    #region Usings

    using System;

    using ExulLibrary.Mathematics.LinearAlgebra.Exceptions;

    #endregion

    /// <summary>
    ///     Represents a solver of system of linear algebraic equations.
    /// </summary>
    /// <typeparam name="T">
    ///     The type of values of elements.
    /// </typeparam>
    public abstract class SlaeSolver<T>
    {
        #region Methods

        #region public

        /// <summary>
        ///     Solves the specified system.
        /// </summary>
        /// <param name="system">
        ///     The system to solve.
        /// </param>
        /// <param name="solution">
        ///     The vector to store the solution.
        /// </param>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="system"/> is <see langword="null"/>.
        ///     <para>
        ///         --or--
        ///     </para>
        ///     <para>
        ///         <paramref name="solution"/> is <see langword="null"/>.
        ///     </para>
        /// </exception>
        /// <exception cref="IncompatibleMatrixVectorException">
        ///     <paramref name="system"/> and <paramref name="solution"/> dimensions are incompatible.
        /// </exception>
        public void Solve(Slae<T> system, DenseVector<T> solution)
        {
            #if SAFE

            if (system == null)
            {
                throw new ArgumentNullException("system");
            }

            if (solution == null)
            {
                throw new ArgumentNullException("solution");
            }

            if (solution.Length < system.Size)
            {
                throw new IncompatibleMatrixVectorException(
                    "system", system.Size, system.Size, "solution", solution.Length, system.Size);
            }

            #endif

            this.SolveSystem(system, solution);
        }

        #endregion

        #region protected

        /// <summary>
        ///     Solves the specified system.
        /// </summary>
        /// <param name="system">
        ///     The system to solve.
        /// </param>
        /// <param name="solution">
        ///     The vector to store the solution.
        /// </param>
        protected abstract void SolveSystem(Slae<T> system, DenseVector<T> solution);

        #endregion

        #endregion
    }
}